package com.atguigu.jxc.service.impl;

import com.atguigu.jxc.dao.GoodsDao;
import com.atguigu.jxc.dao.GoodsTypeDao;
import com.atguigu.jxc.dao.UnitDao;
import com.atguigu.jxc.domain.ServiceVO;
import com.atguigu.jxc.domain.SuccessCode;
import com.atguigu.jxc.entity.Goods;
import com.atguigu.jxc.entity.GoodsType;
import com.atguigu.jxc.entity.Unit;
import com.atguigu.jxc.service.GoodsService;
import com.atguigu.jxc.util.StringUtil;
import com.atguigu.jxc.vo.GoodsTypeVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @description
 */
@Service
public class GoodsServiceImpl implements GoodsService {

    @Autowired
    private GoodsDao goodsDao;

    @Autowired
    private GoodsTypeDao goodsTypeDao;

    @Autowired
    private UnitDao unitDao;

    @Override
    public ServiceVO getCode() {

        // 获取当前商品最大编码
        String code = goodsDao.getMaxCode();

        // 在现有编码上加1
        Integer intCode = Integer.parseInt(code) + 1;

        // 将编码重新格式化为4位数字符串形式
        String unitCode = intCode.toString();

        for (int i = 4; i > intCode.toString().length(); i--) {

            unitCode = "0" + unitCode;

        }
        return new ServiceVO<>(SuccessCode.SUCCESS_CODE, SuccessCode.SUCCESS_MESS, unitCode);
    }

    @Override
    public Map<String, Object> listInventory(Integer page, Integer rows, String codeOrName, Integer goodsTypeId) {
        int pageSize = 30;
        if (rows != null && rows > 0) {
            pageSize = rows;
        }
        int offset = 0;
        if (page != null && page > 1) {
            offset = pageSize * (page - 1);
        }
        List<Integer> goodsTypeIds = new ArrayList<>();

//        List<Goods> goods = goodsDao.listInventory(offset, pageSize, codeOrName, goodsTypeId);
        //优化,选择父节点,实际上子节点应该也能搜到,下边查询孙子 儿子节点的id
////////////////
        List<GoodsType> goodsTypeList = goodsTypeDao.selectAll();

        List<GoodsType> collect = goodsTypeList.stream()
                                               .filter((item) -> item.getGoodsTypeId().equals(goodsTypeId))
                                               .collect(Collectors.toList());


        if (collect.size() == 1) {
            //获取root节点
            GoodsType root = collect.get(0);
            //删除root
            goodsTypeList.remove(root);
            GoodsTypeVo typeRoot = GoodsTypeVo.convertSingle(root);
            //剩下的未分类的
            List<GoodsTypeVo> left = goodsTypeList.stream()
                                                  .map(GoodsTypeVo::convertSingle)
                                                  .collect(Collectors.toList());
            //记录一个最底层节点downList,所有后续添加的子元素的父都在他里保存
            goodsTypeIds.add(goodsTypeId);
            List<GoodsTypeVo> downList = Collections.singletonList(typeRoot);
            int size = left.size();
            while (left.size() != 0) {
                List<GoodsTypeVo> downList2 = new ArrayList<>();


                for (GoodsTypeVo down : downList) {
                    Integer id = down.getId();
                    Iterator<GoodsTypeVo> iterator = left.iterator();

                    while (iterator.hasNext()) {
                        GoodsTypeVo l = iterator.next();
                        Integer pid = l.getPid();
                        if (pid.equals(id)) {
                            //添加到节点下
                            down.getChildren().add(l);
                            //被添加元素成为新的底层元素
                            downList2.add(l);
                            //从剩余里移除被添加元素
                            iterator.remove();
                            goodsTypeIds.add(l.getId());
                        }
                    }
                }
                downList = downList2;
                if (size == left.size()) {
                    break;
                }
                size = left.size();
            }
        }
//////////////


        List<Goods> goods = goodsDao.listInventoryEx(offset, pageSize, codeOrName, goodsTypeIds);

        HashMap<String, Object> map = new HashMap<>();

        map.put("total", goodsDao.listInventoryCountEx(offset, pageSize, codeOrName, goodsTypeIds));
        map.put("rows", goods);

        return map;
    }

    @Override
    public List<GoodsTypeVo> loadGoodsType() {


        List<GoodsType> goodsTypeList = goodsTypeDao.selectAll();

        List<GoodsType> collect = goodsTypeList.stream()
                                               .filter((item) -> item.getPId() == -1)
                                               .collect(Collectors.toList());


        if (collect.size() == 1) {
            //获取root节点
            GoodsType root = collect.get(0);
            //删除root
            goodsTypeList.remove(root);
            GoodsTypeVo typeRoot = GoodsTypeVo.convertSingle(root);
            //剩下的未分类的
            List<GoodsTypeVo> left = goodsTypeList.stream()
                                                  .map(GoodsTypeVo::convertSingle)
                                                  .collect(Collectors.toList());
            //记录一个最底层节点downList,所有后续添加的子元素的父都在他里保存

            List<GoodsTypeVo> downList = Collections.singletonList(typeRoot);
            int size = left.size();
            while (left.size() != 0) {
                List<GoodsTypeVo> downList2 = new ArrayList<>();


                for (GoodsTypeVo down : downList) {
                    Integer id = down.getId();
                    Iterator<GoodsTypeVo> iterator = left.iterator();

                    while (iterator.hasNext()) {
                        GoodsTypeVo l = iterator.next();
                        Integer pid = l.getPid();
                        if (pid.equals(id)) {
                            //添加到节点下
                            down.getChildren().add(l);
                            //被添加元素成为新的底层元素
                            downList2.add(l);
                            //从剩余里移除被添加元素
                            iterator.remove();
                        }
                    }
                }
                downList = downList2;
                if (size == left.size()) {
                    break;
                }
                size = left.size();
            }

            return Collections.singletonList(typeRoot);

        }

        return new ArrayList<>();
    }

    @Override
    public List<Unit> getUnitList() {

        return unitDao.getList();
    }

    @Override
    public Map<String, Object> listNameAndType(Integer page, Integer rows, String goodsName, Integer goodsTypeId) {

        int pageSize = 30;
        if (rows != null && rows > 0) {
            pageSize = rows;
        }
        int offset = 0;
        if (page != null && page > 1) {
            offset = pageSize * (page - 1);
        }

        //优化,选择父节点,实际上子节点应该也能搜到,下边查询孙子 儿子节点的id
        ArrayList<Integer> goodsTypeIds = new ArrayList<>();
////////////////
        List<GoodsType> goodsTypeList = goodsTypeDao.selectAll();

        List<GoodsType> collect = goodsTypeList.stream()
                                               .filter((item) -> item.getGoodsTypeId().equals(goodsTypeId))
                                               .collect(Collectors.toList());


        if (collect.size() == 1) {
            //获取root节点
            GoodsType root = collect.get(0);
            //删除root
            goodsTypeList.remove(root);
            GoodsTypeVo typeRoot = GoodsTypeVo.convertSingle(root);
            //剩下的未分类的
            List<GoodsTypeVo> left = goodsTypeList.stream()
                                                  .map(GoodsTypeVo::convertSingle)
                                                  .collect(Collectors.toList());
            //记录一个最底层节点downList,所有后续添加的子元素的父都在他里保存
            goodsTypeIds.add(goodsTypeId);
            List<GoodsTypeVo> downList = Collections.singletonList(typeRoot);
            int size = left.size();
            while (left.size() != 0) {
                List<GoodsTypeVo> downList2 = new ArrayList<>();


                for (GoodsTypeVo down : downList) {
                    Integer id = down.getId();
                    Iterator<GoodsTypeVo> iterator = left.iterator();

                    while (iterator.hasNext()) {
                        GoodsTypeVo l = iterator.next();
                        Integer pid = l.getPid();
                        if (pid.equals(id)) {
                            //添加到节点下
                            down.getChildren().add(l);
                            //被添加元素成为新的底层元素
                            downList2.add(l);
                            //从剩余里移除被添加元素
                            iterator.remove();
                            goodsTypeIds.add(l.getId());
                        }
                    }
                }
                downList = downList2;
                if (size == left.size()) {
                    break;
                }
                size = left.size();
            }
        }
//////////////
        List<Goods> goods = goodsDao.listByNameAndTypeEx(offset, pageSize, goodsName, goodsTypeIds);

        HashMap<String, Object> map = new HashMap<>();

        map.put("total", goodsDao.listByNameAndTypeCountEx(offset, pageSize, goodsName, goodsTypeIds));
        map.put("rows", goods);

        return map;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean insertType(String goodsTypeName, Integer pId) {
        if (StringUtil.isEmpty(goodsTypeName) || pId == null || pId < 1)
            return false;


        //子节点是0,上边的是1,插入只能插入子节点,所以是0
        //插的时候,检查父节点存在不,并且state应该改成1,
        //删的时候,有子节点不能删,删完了没子节点要改成0


        GoodsType goodsType = new GoodsType(goodsTypeName, 0, pId);

        List<GoodsType> goodsTypeList = goodsTypeDao.selectAll();

        List<GoodsType> collect = goodsTypeList.stream()
                                               .filter((item) -> item.getGoodsTypeId().equals(pId))
                                               .collect(Collectors.toList());
        if (collect.size() < 1) {
            return false;
        }

        GoodsType parent = collect.get(0);

        //这个东西可能刚刚成父节点了,改成1
        if (parent.getGoodsTypeState().equals(0)) {
            parent.setGoodsTypeState(1);
            goodsTypeDao.update(parent);
        }

        goodsType.setPId(parent.getGoodsTypeId());

        goodsTypeDao.save(goodsType);


        return true;


    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteType(Integer goodsTypeId) {
        if (goodsTypeId == null || goodsTypeId < 0) {
            return false;
        }

        //子节点是0,上边的是1,插入只能插入子节点,所以是0
        //插的时候,检查父节点存在不,并且state应该改成1,
        //删的时候,有子节点不能删,删完了没子节点要改成0

        List<GoodsType> goodsTypeList = goodsTypeDao.selectAll();

        List<GoodsType> collect = goodsTypeList.stream()
                                               .filter((item) -> item.getGoodsTypeId().equals(goodsTypeId))
                                               .collect(Collectors.toList());
        if (collect.size() != 1) {
            return false;
        }

        GoodsType toDelete = collect.get(0);

        //  判断是否有子节点,有子节点不能删
        Optional<GoodsType> any = goodsTypeList.stream()
                                               .filter((item) -> item.getPId().equals(toDelete.getGoodsTypeId()))
                                               .findAny();
        if (any.isPresent()) {
            return false;
        }
        //  判断自己是不是当前父的唯一子节点
        //  是的话要把父改成0
        Optional<GoodsType> parent = goodsTypeList.stream()
                                                  .filter((item) -> item.getGoodsTypeId().equals(toDelete.getPId()))
                                                  .findAny();
        if (!parent.isPresent()) {
            return false;
        }

        Integer pid = parent.get().getGoodsTypeId();
        long count = goodsTypeList.stream().filter((item) -> item.getPId().equals(pid)).count();

        if (count == 1) {
            //就一个儿子
            parent.get().setGoodsTypeState(0);
            goodsTypeDao.update(parent.get());
        }

        goodsTypeDao.deleteById(goodsTypeId);

        return true;
    }

    @Override
    public void saveGood(Integer goodsId, Goods good) {
        if (goodsId != null) {
            //更新
            good.setGoodsId(goodsId);
            goodsDao.update(good);
        } else {
            //insert
            good.setInventoryQuantity(0);
            good.setState(0);
            good.setGoodsId(null);
            goodsDao.save(good);
        }
    }

    @Override
    public boolean deleteGood(Integer goodsId) {
        Goods good = goodsDao.selectGood(goodsId);
        if (good.getState().equals(0)) {
            goodsDao.deleteGood(goodsId);
            return true;
        }
        return false;
    }

    @Override
    public Map<String, Object> getNoInventoryQuantity(Integer page, Integer rows, String nameOrCode) {
        int pageSize = 30;
        if (rows != null && rows > 0) {
            pageSize = rows;
        }
        int offset = 0;
        if (page != null && page > 1) {
            offset = pageSize * (page - 1);
        }

        List<Goods> goods = goodsDao.getNoInventoryQuantity(offset, pageSize, nameOrCode);

        HashMap<String, Object> map = new HashMap<>();
        Long count = goodsDao.getNoInventoryQuantityCount();
        map.put("total", count);
        map.put("rows", goods);

        return map;
    }

    @Override
    public Map<String, Object> getHasInventoryQuantity(Integer page, Integer rows, String nameOrCode) {
        int pageSize = 30;
        if (rows != null && rows > 0) {
            pageSize = rows;
        }
        int offset = 0;
        if (page != null && page > 1) {
            offset = pageSize * (page - 1);
        }

        List<Goods> goods = goodsDao.getHasInventoryQuantity(offset, pageSize, nameOrCode);

        HashMap<String, Object> map = new HashMap<>();
        Long count = goodsDao.getHasInventoryQuantityCount();
        map.put("total", count);
        map.put("rows", goods);

        return map;
    }

    @Override
    @Transactional
    public boolean saveGoodStock(Integer goodsId, Integer inventoryQuantity, double purchasingPrice) {
        if (goodsId == null || inventoryQuantity == null) {
            return false;
        }
        Long aLong = goodsDao.updateGoodStock(goodsId, inventoryQuantity, purchasingPrice);

        Goods good = goodsDao.selectGood(goodsId);

        //0是初始化,1是有库存,2是有订单数据
        //如果被设置成0并且原来没订单数据,就设置成0
        //如果原来是2,即使被设置成没库存,也不能变为0,不能删除

        //库存被设置成0了,且状态不是有订单
        if (inventoryQuantity == 0 && good.getState() <= 1) {
            goodsDao.updateGoodStockState(goodsId, 0);
        } else if (good.getState() != 2) {
            goodsDao.updateGoodStockState(goodsId, 1);
        }
        return aLong == 1;
    }
}
